#include "lss_utils.hpp"

ivector null(ivector A) {
    return (A = 0);
}

/*
 * REL computes componentwise the maximum relative error of A w.r.t B.
 * if A[i] and B[i] do not have the same sign or if B[i] = 0, then
 * rel. error = 0 for this component.
 * A is always the new value of an iteration, B the old one.
 * 
 */
real rel(rvector A, rvector B) {
	int  i;
	real p, r, ai, bi;
	const real zerotest = 1e6;
	
	p = 0;
	
	for(i = Lb(A); i <= Ub(A); i++){ // A,B must have same index range
		ai = A[i];
		bi = B[i];
		
		if(((ai * bi) <= 0.0) || ((zerotest * abs(ai)) < abs(bi))) {
		        r = 0.0;
		} else {
			r = abs((ai - bi) / bi);
		}
		
		if(r > p){
			p = r;
		}
	}
	
	return p;
} // end REL


/*
 * TOO_BAD = accuracy of A is far too bad
 * note: 0 for false, 1 for true;
 *
 */
bool too_bad(ivector &A) {
    int  i;
    bool bad;
    const real limit    = 1e20;
    
    bad = false;
    for(i=Lb(A);i<=Ub(A);i++) {
        bad = bad || ((Inf(A[i]) < -limit) && (Sup(A[i]) > limit));
    }
    return bad;
} // end TOO_BAD


/*
 * x1 is the new, x0 the old value of an iteration. If a component of x1
 * has decreased by more than a factor of zerotest, then this component
 * is set to 0. The same is done if the sign of a component has changed.
 */
void guess_zeroes(rvector& x0, rvector& x1) {
	int  i;
	real MAXX;
	const real zerotest = 1e6;
	
	MAXX = 0.0;
	for(i = Lb(x1); i <= Ub(x1); i++){
		if(abs(x1[i]) > MAXX){
			for(i = Lb(x1); i <= Ub(x1); i++){
				if(((x0[i] * x1[i]) < 0.0) || (((zerotest * abs(x1[i])) < abs(x0[i])) && (MAXX > (zerotest * abs(x1[i]))))){
					x1[i] = 0.0;
				}
			}
		}
	}
	
} // end GUESS_ZEROES
